package com.rc.web.mapper;

import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.rc.pojo.dto.area.AreaPageQuery;
import com.rc.pojo.po.Area;
import com.rc.pojo.vo.area.PageAreaVO;

import java.time.LocalDateTime;
import java.util.List;

import static com.rc.pojo.po.table.ActivityTableDef.ACTIVITY;
import static com.rc.pojo.po.table.AreaTableDef.AREA;
import static com.rc.pojo.po.table.PlantTableDef.PLANT;

/**
 * 区域信息表 映射层。
 * 提供区域信息相关的数据库操作接口
 */
public interface AreaMapper extends BaseMapper<Area> {

    /**
     * 分页查询区域信息
     * @param dto 分页查询条件
     * @return 分页结果
     */
    default Page<PageAreaVO> selectPage(AreaPageQuery dto){
        return paginateAs(dto.getCurrent(),dto.getPageSize(), QueryWrapper.create()
                        .select(AREA.ALL_COLUMNS,PLANT.NAME.as("plantName"))
                        .leftJoin(PLANT)
                        .on(PLANT.ID.eq(AREA.PLANT_ID))
                        .where(AREA.NAME.like(dto.getName()))
                , PageAreaVO.class
        );
    }

    /**
     * 根据植物ID查询区域列表
     * @param plantId 植物ID
     * @return 区域列表
     */
    default List<Area> selectByPlantId(long plantId){
        return selectListByQuery(QueryWrapper.create()
                .where(AREA.PLANT_ID.eq(plantId))
        );
    }

    /**
     * 查询季节性区域
     * @param farmId 农场ID
     * @param lng 经度
     * @param lat 纬度
     * @param distance 距离
     * @param type 植物类型
     * @return 区域列表
     */
    default List<Area> selectSeasonal(long farmId,double lng, double lat,int distance,int type){
        // 计算经纬度范围
        double lngDistance = distance * 0.00001141;
        double latDistance = distance * 0.00000899;
        LocalDateTime time = LocalDateTime.now();

        return selectListByQuery(QueryWrapper.create()
                .select(AREA.ALL_COLUMNS)
                .join(PLANT).on(PLANT.ID.eq(AREA.PLANT_ID))
                .join(ACTIVITY).on(ACTIVITY.AREA_ID.eq(AREA.ID))
                .where(AREA.LNG.between(lng - lngDistance,lng + lngDistance))
                .and(AREA.LAT.between(lat - latDistance,lat + latDistance))
                .and(PLANT.TYPE.eq(type))
                .and(ACTIVITY.BEGIN_TIME.le(time))
                .and(ACTIVITY.END_TIME.ge(time))
                .and(ACTIVITY.FARM_ID.eq(farmId))
                .groupBy(AREA.ID)
        );
    }
}
